package com.web.controoller;

import com.web.constant.DataDictionary;
import com.web.constant.DataPackageConstants;
import com.web.observers.RequestResponseObserver;
import com.web.pojo.domain.GateWay;
import com.web.pojo.domain.UserInfo;
import com.web.pojo.vo.AuthorizeDTO;
import com.web.pojo.vo.CommonResult;
import com.web.pojo.vo.GateWayList;
import com.web.service.GateWayServer;
import com.web.service.NetworkServer;
import com.web.service.UserServer;
import com.web.utils.DownLinkDataUtil;
import com.web.utils.SecurityUtils;
import com.web.utils.ToolUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @Author: wws
 * @Date: 2021/1/9 12:07
 * describe:
 */
@CrossOrigin
@RestController
@RequestMapping("/gateway")
public class GateWayController {

    @Autowired
    GateWayServer gateWayServer;
    @Autowired
    NetworkServer networkServer;
    @Autowired
    UserServer userServer;

//    @PostMapping("/insertGateWay")
//    @ApiOperation("添加网关信息")
//    public Callable<CommonResult> insertGateWay(@RequestBody GateWay gateWayInfoPO) throws InterruptedException {
//        byte[] GateWayEui = downLinkDataUntil.toByteArray(gateWayInfoPO.getGatewayEui());
//        byte[] outToken = downLinkDataUntil.CalAppNonce(2);
//        byte[] down = downLinkDataUntil.gatewayRegister(outToken, REGISTER, GateWayEui);
//        Global.getOutQueue().put(down);
//        Callable<CommonResult> callable = new Callable<CommonResult>() {
//            @Override
//            public CommonResult call() throws Exception {
//                for (; ;) {
//                    byte[] take = Global.getInQueue().take();
//                    byte[] inToken = Arrays.copyOfRange(take, 1, 3);
//                    System.out.println(Arrays.toString(inToken));
//                    if (Arrays.equals(inToken, outToken)) {
//                        gateWayServer.insertGateWayInfo(gateWayInfoPO);
//                        return new CommonResult(200, "okk");
//                    }
//                }
//
//            }
//        };
//
//        return callable;
//    }

    @PreAuthorize("hasAuthority('gatewayMInfo:insert')")
    @PostMapping("/getGateWayServers")
    @ApiOperation("查询网络服务器服务")
    public CommonResult getGateWayServers() {
        return CommonResult.select(DataDictionary.gatewayNetworkServers);
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:insert')")
    @PostMapping("/getGateWayProfiles")
    @ApiOperation("查询网关协议")
    public CommonResult getGateWayProfiles() {
        return CommonResult.select(DataDictionary.gateWayProfiles);
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:insert')")
    @PostMapping("/insert")
    @ApiOperation("添加网关信息")
    public CommonResult insertGateWayInfo(@RequestBody GateWay gateWay) throws InterruptedException {
        if (!ToolUtil.checkIsHexadecimal(gateWay.getGatewayEui()) || gateWay.getGatewayEui().length() != 16) {
            return CommonResult.error("该网关EUI格式错误");
        }
        if (!gateWayServer.checkGateWayEuiUnique(gateWay.getGatewayEui())) {
            return CommonResult.fail("该网关EUI已被注册");
        }
        return gateWayBridge(gateWay);
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:updata')")
    @PostMapping("/update")
    @ApiOperation("修改网关信息")
    public CommonResult updateGateWayInfo(@RequestBody GateWay gateWayInfo) {
        gateWayInfo.setUpdateBy(SecurityUtils.getUsername());
        return CommonResult.update(gateWayServer.updateGateWayInfo(gateWayInfo));
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:delete')")
    @PostMapping("/delete")
    @ApiOperation("删除网关信息")
    public CommonResult deleteGateWayInfo(@RequestBody List<Integer> gateWayIds) {
        if (gateWayIds.isEmpty()) {
            return CommonResult.error("未选择要删除的网关");
        }
        String updateBy = SecurityUtils.getUsername();
        return CommonResult.delete(gateWayServer.deleteGateWayInfo(gateWayIds, updateBy));
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:select')")
    @PostMapping("/selectList")
    @ApiOperation("查看网关列表")
    public CommonResult selectGateWayList(@RequestBody(required = false) String str) {
        Integer userId = SecurityUtils.getUserId();
        List<GateWayList> list = gateWayServer.selectGateWayList(userId, str);
        return CommonResult.select(list);
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:select')")
    @PostMapping("/selectGateWayListByAddress")
    @ApiOperation("根据地址查询网关列表")
    public CommonResult selectGateWayListByAddress(@RequestBody Integer addressId) {
        Integer userId = SecurityUtils.getUserId();
        List<GateWay> list = gateWayServer.selectGateWayListByAddress(userId, addressId);
        return CommonResult.select(list);
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:select')")
    @PostMapping("/details")
    @ApiOperation("查看网关详细信息")
    public CommonResult selectGateWayDetails(@RequestBody Integer gateWayId) {
        GateWay gateWayInfo = gateWayServer.selectGateWayDetails(gateWayId);
        return CommonResult.select(gateWayInfo);
    }

    @PreAuthorize("hasAuthority('gatewayMInfo:insert')")
    @PostMapping("/checkGateWayEuiUnique")
    @ApiOperation("检查eui是否正确")
    public CommonResult checkGateWayEuiUnique(@RequestBody(required = false) String gateWayEui) {
        if (gateWayEui == null) {
            return CommonResult.error("请输入网关EUI");
        }
        if (!ToolUtil.checkIsHexadecimal(gateWayEui) || gateWayEui.length() != 16) {
            return CommonResult.error("该网关EUI格式错误");
        }
        if (!gateWayServer.checkGateWayEuiUnique(gateWayEui)) {
            return CommonResult.fail("该网关EUI已被注册");
        }
        return CommonResult.success("该网关Eui可以注册");
    }

    @PostMapping("/authorize")
    @ApiOperation("授权")
    private CommonResult authorizeGateWay(@RequestBody AuthorizeDTO dto) {
        UserInfo userInfo = userServer.selectUserInfoByUsername(dto.getUsername());
        if (userInfo == null) {
            return CommonResult.error("用户不存在");
        }
        gateWayServer.authorizeGateWay(dto.getIds(),userInfo.getUserId());
        return CommonResult.success("授权成功");
    }


    private CommonResult gateWayBridge(@RequestBody GateWay gateWay) throws InterruptedException {
        byte[] gateWayEui = ToolUtil.toByteArray(gateWay.getGatewayEui());
        byte[] token = ToolUtil.CalAppNonce(2);
        byte[] down = DownLinkDataUtil.gatewayRegister(token, DataPackageConstants.REGISTER, gateWayEui);
        RequestResponseObserver gatewayResponse = new RequestResponseObserver(token);
        CompletableFuture<Boolean> isDown = networkServer.downstreamData(down);
        CompletableFuture<Boolean> isResponse = networkServer.checkGateWayResponse(gatewayResponse);

        try {
            isDown.get(5, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            CommonResult.error("错误，下位机未开启");
        }
        try {
            isResponse.get(5, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            CommonResult.error("错误，下位机未响应");
        }
        return CommonResult.insert(gateWayServer.insertGateWayInfo(gateWay));
    }



}
